/*  -*- mode: c++; coding: utf-8; c-file-style: "stroustrup"; -*-

    Copyright 2008 Asier Aguirre <asier.aguirre@gmail.com>
    This file is part of Intromit.

    Intromit is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Intromit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Intromit.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef TIME_QUEUE_HH
#define TIME_QUEUE_HH
//! \addtogroup util
//@{

#include "util.hh"

// DECLARATIONS
class reference_counter;

// TYPEDEFS
// callback proto: if returns <0, event is forgotten
typedef int (*time_queue_callback)(reference_counter *obj, void *data);

class time_queue
{
    // TYPES
    struct queue_object
    {
	time_queue_callback callback; // if NULL => hole
	reference_counter *obj;
	void *data;
    };

    struct queue
    {
	int i_queue_obj;
	unsigned time;
    };

    // registered objects
    queue_object *obj;
    int n_obj, max_obj;

    // queue
    queue *q;
    int q_ini, q_end; // eq_ini > eq_end; eq_end event will be taken out first

    // PRIVATE METHODS
    void ctor();
    void dtor();

    // queue
    void extract_first();
    void add(int i_queue_obj, unsigned time);
    void del(int position);
    static unsigned time_now();
    static bool time_compare(unsigned time1, unsigned time2); // returns true if time1 >= time2

public:
    time_queue();
    ~time_queue();

    // add an event to queue: func must be non-static and obj, ref. counted
    bool add(time_queue_callback callback, reference_counter *obj=NULL, void *data=NULL);
    bool remove(time_queue_callback callback=NULL, reference_counter *obj=NULL, void *data=NULL);
    bool remove_all();
    bool refresh(bool control_idle_time=false);
};

//@}
#endif

/* Offline metadata attributes:

   @metadata_attrs(
	time_queue
	{
		# members
		:
						select

		# methods
		remove_all:
						select
	}
   )
*/
